package supernova

type ColumnFlag int
type ColumnType string

const (
	TINYINT  ColumnType = "tinyint"
	INT      ColumnType = "int"
	VARCHAR  ColumnType = "varchar"
	TEXT     ColumnType = "text"
	DATETIME ColumnType = "datetime"
)

type IndexType string

const (
	PrimaryIndex  IndexType = "PRIMARY"
	UniqueIndex   IndexType = "UNIQUE KEY"
	FulltextIndex IndexType = "FULLTEXT KEY"
	KeyIndex      IndexType = "KEY"
)

type Column struct {
	Field   string     `json:"field" yaml:"field"`
	Type    ColumnType `json:"type" yaml:"type"`
	Length  int        `json:"length" yaml:"length"`
	Default string     `json:"default" yaml:"default"`
	Flag    ColumnFlag `json:"flag" yaml:"flag"`
	Comment string     `json:""`
}

func (column *Column) IsDiff(other *Column) bool {
	if column.Field != other.Field {
		return true
	}
	if column.Type != other.Type {
		return true
	}
	if column.Length != other.Length {
		return true
	}
	if column.Default != other.Default {
		return true
	}
	if column.Flag != other.Flag {
		return true
	}
	if column.Comment != other.Comment {
		return true
	}
	return false
}

func (column *Column) Format(v interface{}) interface{} {
	if v == nil {
		return nil
	}
	//switch column.Type {
	//case VARCHAR:
	//	fallthrough
	//case DATETIME:
	//	fallthrough
	//case TEXT:
	//	return string(v.([]byte))
	//case INT:
	//	fallthrough
	//case TINYINT:
	//	return utils.ToInt(string(v.([]byte)))
	//}
	return v
}

type Index struct {
	Type   IndexType `json:"type" yaml:"type"`
	Name   string    `json:"name" yaml:"name"`
	Fields []string  `json:"fields" yaml:"fields"`
	Extend string    `json:"extend" yaml:"extend"`
}

func (index *Index) IsDiff(other *Index) bool {
	if index.Type != other.Type {
		return true
	}
	if index.Name != other.Name {
		return true
	}
	if len(index.Fields) != len(other.Fields) {
		return true
	}
	for index, field := range index.Fields {
		if field != other.Fields[index] {
			return true
		}
	}
	return false
}

type Foreign struct {
	Name          string `json:"name" yaml:"name"`
	Field         string `json:"field" yaml:"field"`
	RelationTable string `json:"relation_table" yaml:"relation_table"`
	RelationField string `json:"relation_field" yaml:"relation_field"`
}

func (foreign *Foreign) IsDiff(other *Foreign) bool {
	if foreign.Name != other.Name {
		return true
	}
	if foreign.Field != other.Field {
		return true
	}
	if foreign.RelationTable != other.RelationTable {
		return true
	}
	if foreign.RelationField != other.RelationField {
		return true
	}
	return false
}

type Table struct {
	Name     string     `json:"name" yaml:"name"`
	Columns  []*Column  `json:"columns" yaml:"columns"`
	Indexs   []*Index   `json:"indexs" yaml:"indexs"`
	Foreigns []*Foreign `json:"foreigns" yaml:"foreigns"`
	Auto     int        `json:"auto" yaml:"auto"`

	columnMap  map[string]int `json:"-" yaml:"-"`
	indexMap   map[string]int `json:"-" yaml:"-"`
	foreignMap map[string]int `json:"-" yaml:"-"`
}

func (table *Table) analysis() {
	table.columnMap = map[string]int{}
	table.indexMap = map[string]int{}
	table.foreignMap = map[string]int{}

	for index, column := range table.Columns {
		table.columnMap[column.Field] = index
	}

	for i, index := range table.Indexs {
		table.indexMap[index.Name] = i
	}

	for i, foreign := range table.Foreigns {
		table.foreignMap[foreign.Name] = i
	}
}

func (table *Table) Diff(other *Table) *Diff {
	return NewDiff(table, other)
}
